import http from '@ohos.net.http';
import { StrUtil } from '../utils/StrUtil';
import { HttpConfig, HttpRequestMethod } from './HttpConfig';
const noonFunc = () => {};
/**
 * Axios请求封装
 * @author BXMing
 */
export class Axios {
  interceptors;
  config: HttpConfig;
  constructor() {
    // 定义拦截器对象
    this.interceptors = {
      // 请求拦截
      request: {
        // 给函数绑定当前的this，否则this会指向request
        use: this.beforeRequest.bind(this),
        success: noonFunc,
        fail: noonFunc
      },
      // 响应拦截
      response: {
        use: this.beforeResponse.bind(this),
        success: noonFunc,
        fail: noonFunc
      }
    };
    // 默认配置文件
    this.config = {
      baseURL: 'http://127.0.0.1',
      timeout: 6000,
      method: HttpRequestMethod.GET,
      contentType: "application/json",
      authorization: ""
    };
  }

  // Axios的初始化函数，初始化时对config进行赋值
  static create({
    baseURL = "",
    timeout = 6000,
    method = HttpRequestMethod.GET,
    contentType = "application/json",
    authorization = ""
                } = {}) {
    const axios = new Axios();
    axios.config = {
      baseURL,
      timeout,
      method,
      contentType,
      authorization
    }
    return axios;
  }

  // 请求发送前的拦截函数
  beforeRequest() {
    /**
     * 成功拦截函数，传入一个config
     * 调用拦截的时候，会调用传入的successFunc函数
     */
    this.interceptors.request.success = (config) => {
      return config;
    }
    this.interceptors.request.fail = (error) => {
      return Promise.reject(error);
    }
  }
  // 请求响应的拦截函数
  beforeResponse() {
    this.interceptors.response.success = (response) => {
      return response;
    }
    this.interceptors.response.fail = (error) => {
      return Promise.reject(error);
    }
  }

  // 通用request函数
  async request(url, data, {
    method = this.config.method,
    contentType = this.config.contentType,
    timeout = this.config.timeout,
    authorization = this.config.authorization
  } = {}) {
    let config: HttpConfig = {
      baseURL: url,
      data,
      method,
      contentType,
      timeout,
      authorization
    }
    // 如果是http://，https://开头的则不走拦截
    if (StrUtil.checkIsOriginRequest(url)) {
      return this.sendRequest(config);
    }
    return new Promise(async (resolve, reject) => {
      config = await this.interceptors.request.success(config);
      if (!config) {
        return;
      }
      await this.sendRequest(config).then(requestResponse => {
        console.log("AxiosRequestResponse: " + JSON.stringify(requestResponse));
        let response = {
          statusCode: requestResponse.responseCode,
          config,
          data: requestResponse.result,
          header: requestResponse.header
        };
        const result = this.interceptors.response.success(response);
        if (StrUtil.checkIsPromise(result)) {
          result.catch(err => {
            reject(err);
          })
        } else {
          resolve(result);
        }
      }).catch(requestError => {
        console.error("AxiosRequestError: " + JSON.stringify(requestError));
        let error = {
          error: requestError,
          response: {
            statusCode: requestError.statusCode,
            config,
            data: requestError.data,
            header: requestError.header,
            errMsg: requestError.errMsg
          }
        }
        const failResult = this.interceptors.response.fail(error);
        if (StrUtil.checkIsPromise(failResult)) {
          failResult.catch(err => {
            reject(err);
          })
        } else {
          reject(failResult);
        }
      })
    })
  }

  // 发送请求
  sendRequest(config: HttpConfig): Promise<http.HttpResponse> {
    return new Promise((resolve, reject) => {
      // 每一个httpRequest对应一个HTTP请求任务，不可复用
      let httpRequest = http.createHttp();
      httpRequest.request((StrUtil.checkIsOriginRequest(config.baseURL) ? '' : this.config.baseURL + config.baseURL), {
        method: config.method == HttpRequestMethod.GET ? http.RequestMethod.GET : http.RequestMethod.POST,
        header: {
          'Content-Type': config.contentType,
          'Authorization': config.authorization
        },
        extraData: config.data,
        connectTimeout: config.timeout,
        readTimeout: config.timeout
      }).then((res) => {
        if (res.responseCode == http.ResponseCode.NOT_FOUND) {
          reject(res);
          return;
        }
        resolve(res);
      }).catch((err) => {
        reject(err);
      })
    })
  }

  // get请求
  get(url, data?, {
    timeout = this.config.timeout,
    contentType = this.config.contentType,
    authorization = this.config.authorization
  } = {}) {
    return this.request(url, data, {
      method: HttpRequestMethod.GET,
      timeout,
      contentType,
      authorization
    })
  }

  // post请求
  post(url, data, {
    timeout = this.config.timeout,
    contentType = this.config.contentType,
    authorization = this.config.authorization
  } = {}) {
    return this.request(url, data, {
      method: HttpRequestMethod.POST,
      timeout,
      contentType,
      authorization
    })
  }
}